////////////////////////////////////////////////
// DESCRIPTION:
//    FusionWare::DFX - Stream API interface library.
//
// Legal Notices:
//     Copyright (c) 2008, Telliam Consulting, LLC.
//     All rights reserved.
//
//     Redistribution and use in source and binary forms, with or without modification,
//     are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//
//     * Neither the name of Telliam Consulting nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// Disclaimer:
//     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//     IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
//     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
//     OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
//     OF THE POSSIBILITY OF SUCH DAMAGE.  
//
#pragma once

#include <windows.h>
#include <handle_map.hxx>
#include <pm.h>
#include <FusionWare\DFX.h>
#include <FusionWare\Win32.h>
#include <FusionWare\Interfaces.h>
#include "DeviceWindows.h"
#include "DeviceRegValues.h"

namespace FusionWare
{
    namespace DFX
    {
       
        ///////////////////////////////////////////////////////
        // Description: 
        //    Interface for a stream drivers "Open Context"
        //
        [uuid("DEDE83EE-9E34-4d76-9E8E-25C6B316DB58")]
        class ITF_NOVTABLE IOpenContext : virtual public FusionWare::Interfaces::IGuidCast
        {
        public:
   	        virtual bool  Init(DWORD AccessCode, DWORD ShareMode) = 0;
            virtual DWORD Seek(long Amount, DWORD Type) = 0;
	        virtual DWORD Read(void* pBuffer, DWORD Count) = 0 ; 
	        virtual DWORD Write(const void* pSourceBytes, DWORD NumberOfBytes) = 0;
            virtual bool  PreClose() = 0;
            virtual bool  IoControl(DWORD IoCode, BYTE* pInBuf, DWORD InBufSize, BYTE* pOutBuf, DWORD OutBufSize, DWORD* pActualOut, bool* pRetVal)=0; 
        };

        DECLARE_INTERFACE_PTR(IOpenContext);

        ///////////////////////////////////////////////////////
        // Description: 
        //    Interface for a stream drivers "Driver Context"
        //
        [uuid("25FB2500-2EEC-45a0-B942-1E74D5DE1545")]
        class ITF_NOVTABLE IDriverContext : virtual public FusionWare::Interfaces::IGuidCast
        {
        public:
            virtual bool Init(const TCHAR* RegPath)=0;
            virtual bool PreDeinit()=0;
            virtual void Deinit()=0;
            virtual bool Open(DWORD AccessCode, DWORD ShareMode, IOpenContext** ppContext)=0; 
            virtual bool IoControl(DWORD IoCode, BYTE* pInBuf, DWORD InBufSize, BYTE* pOutBuf, DWORD OutBufSize, DWORD* pActualOut, bool* pRetVal)=0;
            virtual void PowerUp()=0;
            virtual void PowerDown()=0;
        };

        DECLARE_INTERFACE_PTR(IDriverContext);


        ///////////////////////////////////////////////////////
        // Description: 
        //    Partial implementation of IDriverContext
        //
        class IDriverContextImpl
            : public IDriverContext
            , public FusionWare::Interfaces::IGuidCastImpl
        {
        public:
            IDriverContextImpl() {}
            virtual ~IDriverContextImpl() {}
        
            BEGIN_INTERFACE_MAP(IDriverContextImpl)
                INTERFACE_MAP_ENTRY(IDriverContext)
            END_INTERFACE_MAP

        public:
            //virtual bool Init(const TCHAR* RegPath)=0;
            virtual bool PreDeinit();
            virtual void Deinit();
            //virtual bool Open(DWORD AccessCode, DWORD ShareMode, IOpenContext** ppContext)=0; 
            virtual bool IoControl(DWORD IoCode, BYTE* pInBuf, DWORD InBufSize, BYTE* pOutBuf, DWORD OutBufSize, DWORD* pActualOut,bool* pRetVal);

            // not pure virtual to provide an empty default

            virtual void PowerUp(); 
            virtual void PowerDown();

            // Ioctl handlers for power manager control codes
        protected:
            virtual bool QueryPowerCapabilities(const POWER_RELATIONSHIP* pRelationship, POWER_CAPABILITIES* pCaps);
            virtual bool QueryPowerState(const POWER_RELATIONSHIP* pRelationship, CEDEVICE_POWER_STATE* pState);
            virtual bool QueryPowerStateChange(const POWER_RELATIONSHIP* pRelationship, CEDEVICE_POWER_STATE* pState);
            virtual bool SetPowerState(const POWER_RELATIONSHIP* pRelationship, CEDEVICE_POWER_STATE* pState);
            virtual bool RegisterPowerRelationships();

        protected:
            // locking of the driver should be managed internal to the driver
            // context itself and not anything external to it.
            void Lock()   { this->cs.Lock(); }
            void Unlock() { this->cs.Unlock(); }
            
            FusionWare::Threads::CriticalSection cs;       // Critical Section to protect access
        };
        
        ///////////////////////////////////////////////////////
        // Description: 
        //    Partial implementation of IOpenContext
        //
        // Remarks:
        //   This simply implements stubs for the basic stream
        //   functions that are typilcally not implemented. 
        //   they each return an appropriate not implemented
        //   error code.
        //
        class IOpenContextImpl
            : public IOpenContext
            , public FusionWare::Interfaces::IGuidCastImpl
        {
        public:
            IOpenContextImpl();
	        virtual ~IOpenContextImpl();

            BEGIN_INTERFACE_MAP(IOpenContextImpl)
                INTERFACE_MAP_ENTRY(IOpenContext)
            END_INTERFACE_MAP

        // Group = Virtuals with default behaviours
        public:
   	        virtual bool  Init(DWORD AccessCode, DWORD ShareMode);
            virtual DWORD Seek(long Amount, DWORD Type);
	        virtual DWORD Read(void* pBuffer, DWORD Count); 
	        virtual DWORD Write(const void* pSourceBytes, DWORD NumberOfBytes);
            virtual bool  PreClose();

            //  Pure virtuals from IOpenContext - no default implementation
            //  virtual bool IoControl(DWORD IoCode,BYTE* pInBuf, DWORD InBufSize, BYTE* pOutBuf, DWORD OutBufSize, DWORD* pActualOut, bool* pRetVal)=0; 

        public:
            ///////////////////////////////////////////////////////
            // Description: 
            //    Provides the stored Access and sharing state info.
            //
            // Output: 
            //    pAccessCode - Access code flags used to create this open
            //                  context.
            //    pShareMode  - Shareing Mode used to create this context. 
            //
            // Returns: 
            //     void 
            //     
            void GetShareInfo(DWORD* pAccessCode, DWORD* pShareMode)
            {
                ASSERT(pAccessCode!=NULL && pShareMode!=NULL);

                *pAccessCode = this->AccessCode;
                *pShareMode = this->ShareMode;
            }

        protected:
   	        DWORD AccessCode;
	        DWORD ShareMode;
        };

        /////////////////////////////////////////////////////////////
        // Description:
        //    Map of all driver contexts managed by this driver
        //  
        // Remarks:
        //    Each driver instance listed in the registry or loaded
        //    by ActivateDeviceEx has a driver context associated to it. 
        //    this map keeps track of all the valid ones so that the
        //    Stream APIs can detect invalid context values sent from 
        //    the device manager.
        // 
        typedef HandleMap<IDriverContextPtr> DriverContextMap;
        
        /////////////////////////////////////////////////////////////
        // Description:
        //    Map of all Open contexts managed by this driver
        //  
        // Remarks:
        //    Each time the device is opened a new open context is created.
        //    that context is mapped here to create and validate the handles
        //    used by the Device manager for the open context.
        // 
        typedef HandleMap<IOpenContextPtr> OpenContextMap;

        /////////////////////////////////////////////////////////////
        // Description:
        //    Creates and instance of the driver context.
        //
        // Input:
        //    Context - Driver context provided to xxx_Init()
        // 
        // Output:
        //    ppDrv - Driver context interface
        // 
        // Remarks:
        //    This acts as the object factory for the driver context
        //    it is implemented by each driver to create an instance
        //    of that drivers specific driver context, which implements
        //    IDriverContext. The standard Stream "forwarding stubs"
        //    use this to create the driver context. Sometimes, the
        //    implementation of this function
        //
        extern bool CreateDriverContext(DWORD Context, FusionWare::DFX::IDriverContext** ppDrv);
    }
}

#ifdef DEBUG
// Each driver must define the details of the
// standard DBGPARAM data structure as needed
extern "C" DBGPARAM dpCurSettings;
#endif
